<?php
/**
 * A database query object
 *
 * Uses MySQLi PHP library (MySQL 4.1+)
 * @link http://webappkit.net
 * @package webappkit
 * @subpackage db
 * @author P.Buth
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 */
class DbQuery /*implements iDbQuery*/
{
    /**
     * Get the whole SQL query of the specified type
     *
     * @param string $type select|count|insert|delete|update
     * @return string
     */
    public function getSql($type)
    {
        $sql_string   = '';

        switch(strtolower($type)) {

            case 'select' :
                $sql_string = $this->_buildSelectQuery();
                break;

            case 'count' :
                $sql_string = $this->_buildCountQuery();
                break;

            case 'insert' :
                $sql_string = $this->_buildInsertQuery();
                break;

            case 'delete' :
                $sql_string = $this->_buildDeleteQuery();
                break;

            case 'update' :
                $sql_string = $this->_buildUpdateQuery();
                break;

            default :
                return false;

        }

        return $sql_string;
    }

    /**
     * Adds a WHERE clause
     *
     * All clauses will be chained by AND
     *
     * @param  string $sql statement
     * @param  string $key optional, may be used to remove the clause
     * @return bool
     */
    public function addWhere($sql, $key = null)
    {
        if(!is_string($sql)) {
            return false;
        }
        
        if(is_string($key)) {
            $this->where_clauses[$key] = $sql;
        } else {
            $this->where_clauses[] = $sql;
        }

        return true;
    }

    /**
     * Removes one or all WHERE clauses
     *
     * @param  string $key
     * @return bool
     */
    public function removeWhere($key)
    {
        if(!array_key_exists($key, $this->where_clauses)) {
            return false;
        }

        unset($this->where_clauses[$key]);

        if(array_key_exists($key, $this->where_clauses)) {
            return false;
        }

        return true;
    }

    /**
     * Removes all WHERE clauses
     *
     * @return bool
     */
    public function flushWhere()
    {
        $this->where_clauses = array();

        return true;
    }

    /**
     * Get the WHERE statement as SQL
     *
     * Ex. "hair='brown' AND feets=2"
     *
     * @return string
     */
    public function getWhere()
    {
        $where_str = '';
        $where_str = implode(" AND ", $this->where_clauses);

        return $where_str;
    }

    /**
     * Sets the ORDER BY statement
     *
     * @param  string $sql
     * @return bool
     */
    public function setOrder($sql)
    {
        if(!is_string($sql)) {
            return false;
        }

        $this->sql_order = $sql;

        return true;
    }

    /**
     * Get back the ORDER BY statement
     *
     * @return string
     */
    public function getOrder()
    {
        return $this->sql_order;
    }

    /**
     * Sets the LIMIT statement
     *
     * @param  string $sql
     * @return bool
     */
    public function setLimit($sql)
    {
        if(!is_string($sql)) {
            return false;
        }

        $this->sql_limit = $sql;

        return true;
    }

    /**
     * Get back the LIMIT statement
     *
     * @return string
     */
    public function getLimit()
    {
        return $this->sql_limit;
    }

    /**
     * Sets the SELECT part
     *
     * Ex. 'u.screen_name, u.email'
     * $sql default value  " * "
     *
     * @param  string $sql
     * @return bool
     */
    public function setSelect($sql = ' * ')
    {
        if(!is_string($sql)) {
            return false;
        }

        $this->sql_select = $sql;

        return true;
    }

    /**
     * Get back the SELECT part
     *
     * @return string
     */
    public function getSelect()
    {
        return $this->sql_select;
    }

    /**
     * Sets the FROM part
     *
     * Ex. 'users AS u LEFT JOIN cars AS c ON c.user_id=u.id'
     *
     * @param string $sql
     * @return bool
     */
    public function setFrom($sql)
    {
        if(!is_string($sql)) {
            return false;
        }

        $this->sql_from = $sql;

        return true;
    }

    /**
     * Get back the FROM part
     *
     * @return string
     */
    public function getFrom()
    {
        return $this->sql_from;
    }

    /**
     * Sets the COUNT sql part
     *
     * Ex. 'COUNT(*)'
     *
     * @param  string $sql
     * @return bool
     */
    public function setCount($sql = '*')
    {
        if(!is_string($sql)) {
            return false;
        }

        $this->sql_count = $sql;

        return true;
    }

    /**
     * Get back the COUNT part
     *
     * @return string
     */
    public function getCount()
    {
        return $this->sql_count;
    }

    /**
     * Sets the INSERT part
     *
     * Ex. "users SET login='toto', password='secret'"
     *
     * @param  string $sql
     * @return bool
     */
    public function setInsert($sql)
    {
        if(!is_string($sql)) {
            return false;
        }

        $this->sql_insert = $sql;

        return true;
    }

    /**
     * Get back the INSERT part
     *
     * @return string
     */
    public function getInsert()
    {
        return $this->sql_insert;
    }

    /**
     * sets the UPDATE part
     *
     * Ex. "users SET login='toto', password='secret'"
     *
     * @param string $sql
     * @return bool
     */
    public function setUpdate($sql)
    {
        if(!is_string($sql)) {
            return false;
        }

        $this->sql_update = $sql;

        return true;
    }

    /**
     * Get back the UPDATE part
     *
     * @return string
     */
    public function getUpdate()
    {
        return $this->sql_update;
    }

    /**
     * @var string select|insert|update
     */
    protected $type;

    /**
     * @var string SQL SELECT statement (without SELECT)
     */
    protected $sql_select;

    /**
     * @var string SQL COUNT statement (without COUNT)
     */
    protected $sql_count;

    /**
     * @var string SQL INSERT statement (without INSERT)
     */
    protected $sql_insert;

    /**
     * @var string SQL DELETE statement (without INSERT)
     */
    protected $sql_delete;

    /**
     * @var string SQL UPDATE statement (without INSERT)
     */
    protected $sql_update;

    /**
     * @var string SQL FROM (without FROM)
     */
    protected $sql_from;

    /**
     * @var array WHERE clauses
     */
    protected $where_clauses = array();

    /**
     * @var string SQL ORDER BY
     */
    protected $sql_order;

    /**
     * @var string SQL LIMIT
     */
    protected $sql_limit;

    /**
     * Build and return a SELECT query string
     *
     * @return string|false
     */
    protected function _buildSelectQuery()
    {
        $query_strings = '';
        $where         = '';
        $order         = '';
        $limit         = '';

        if($this->getSelect() == NULL || $this->getFrom() == NULL) {
            return false;
        }

        $where = $this->getWhere();
        $order = $this->getOrder();
        $limit = $this->getLimit();

        $query_string  = 'SELECT ' . $this->getSelect() . ' FROM ' . $this->getFrom();
        $query_string .= $where != false ? ' WHERE ' . $where : '';
        $query_string .= $order != false ? ' ORDER BY ' . $order : '';
        $query_string .= $limit != false ? ' LIMIT ' . $limit : '';

        return $query_string;
    }

    /**
     * Build and return a SELECT COUNT() query string
     *
     * @return string
     */
    protected function _buildCountQuery()
    {
        $query_strings = '';
        $where         = '';

        if($this->getCount() == NULL || $this->getFrom() == NULL) {
            return false;
        }

        $where = $this->getWhere();

        $query_string  = 'SELECT COUNT(' . $this->getCount() . ') AS count FROM ' . $this->getFrom();
        $query_string .= $where != false ? ' WHERE ' . $where : '';

        return $query_string;
    }

    /**
     * Build and return an INSERT query string
     *
     * @return string
     */
    protected function _buildInsertQuery()
    {
        $query_strings = '';

        if($this->getFrom() == NULL ) {
            return false;
        }

        $query_string  = 'INSERT INTO ' . $this->getFrom() . ' SET ' . $this->getInsert();

        return $query_string;
    }

    /**
     * Build and return a DELETE query string
     *
     * @return string
     */
    protected function _buildDeleteQuery()
    {
        $query_strings = '';
        $where         = $this->getWhere();
        $limit         = $this->getLimit();

        if($where == false || $where == '') {
            return false;
        }

        $query_string  = 'DELETE FROM ' . $this->getFrom() . ' WHERE ' . $where;
        $query_string .= $limit != false ? ' LIMIT ' . $limit : '';

        return $query_string;
    }

    /**
     * Build and return an UPDATE query string
     *
     * @return string|false
     */
    protected function _buildUpdateQuery()
    {
        $query_string = '';

        if($this->getFrom() == '' || $this->getUpdate() == '') {
            return false;
        }

        $query_string  = 'UPDATE ' .  $this->getFrom() . ' ';
        $query_string .= 'SET ' . $this->getUpdate() . ' ';
        $query_string .= $this->getWhere()  != '' ? 'WHERE ' . $this->getWhere() : '';

        return $query_string;
    }

}
